#include <QObject>
#include <QFileDialog>
#include <iostream>
#include "inc/mainwindow.h"
#include "ui_interface.h"

#define ARIA_MD5SUM "96b335b29bb7cf7c603b47e1d4c8b8d5"

/*
 * Class initialisator.
 * What shit is need to be done here:
 * - setup ui
 * - set fixed size
 * - get rid of , instead of . (;_;)
 * - set title for window
 * - load image into program
 * - connect slots and signals
 * - load previously saved configuration (if there is any)
 * */
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
	ui->setupUi(this);
	setFixedSize(506,318);
	setlocale(LC_NUMERIC,"C");
	setWindowTitle(QString::fromUtf8("Aria linux client manager"));

	// 10.02.12 -> added proper image directory handeling
	QString* image_directory = new QString;
	image_directory->push_back(QDir::homePath());
	image_directory->push_back("/.config/aria/logo.png");
	this->image.load(*image_directory);
	ui->label_image->setPixmap(this->image);
	
	//connect signals to slots ------------------------------
	QObject::connect(ui->button_change_directory ,	SIGNAL(clicked()), this, SLOT(directory_change())	);
	QObject::connect(ui->button_save,		SIGNAL(clicked()), this, SLOT(configuration_save())	);
	QObject::connect(ui->button_check,		SIGNAL(clicked()), this, SLOT(directory_check())	);
	QObject::connect(ui->button_client_1,		SIGNAL(clicked()), this, SLOT(run_client_1())		);
	QObject::connect(ui->button_client_2,		SIGNAL(clicked()), this, SLOT(run_client_2())		);
	QObject::connect(ui->button_close_1,		SIGNAL(clicked()), this, SLOT(close_client_1())		);
	QObject::connect(ui->button_close_2,		SIGNAL(clicked()), this, SLOT(close_client_2())		);
	//-------------------------------------------------------
	//load previously saved configuration
	settings.beginGroup("lineage_client");
	path_to_ariaupdate = settings.value("updater_location").toString();
	if( !path_to_ariaupdate.isNull() ) {
		ui->label_path->setText(path_to_ariaupdate);
	}
	client_width 	= settings.value("window_width").toInt();
	if(client_width > 0 && client_width < 3000) {
		ui->textEdit->setText(QString::number(client_width));
	}
	else{
		client_width = 800;
		ui->textEdit->setText("800");
	}
	client_height	= settings.value("window_height").toInt(); 
	if(client_height > 0 && client_height < 3000) {
		ui->textEdit_2->setText(QString::number(client_height));
	}
	else {
		client_height = 600;
		ui->textEdit_2->setText("600");
	}
	settings.endGroup();
	ui->textEdit->setAlignment(Qt::AlignCenter);
	ui->textEdit_2->setAlignment(Qt::AlignCenter);
	//-------------------------------------------------------
}
/*
 * Just deconstructor, carry on
 * */
MainWindow::~MainWindow() {
	delete ui;
}
/*
 * Action for using the mysterious "change directory" button.
 * Opens up a dialog window to choose a file, then sets its path in
 * local variable.
 * */
void MainWindow::directory_change() {
	path_to_ariaupdate = QFileDialog::getOpenFileName( this, tr("point file to open"), QDir::currentPath(), tr("aria updater (*.exe)") );
	if( !path_to_ariaupdate.isNull() ) {
		ui->label_path->setText(path_to_ariaupdate);
	}
}
/*
 * Here we compare the md5 sum of targeted file and the value already stored
 * in program to determine if the file (even though it might share the same name)
 * is the real updater.
 * It's optional, as everything else in program. User can launch the clients even
 * without this step.
 * */
void MainWindow::directory_check() {
	if(path_to_ariaupdate.isEmpty())
		return;

	FILE	*check_md5sum_stream;
	char	buffer[100];
	QByteArray   bytes  = path_to_ariaupdate.toAscii();
	const char * ptr    = bytes.data();
	char*	md5sum_obtained;
	int	err;
	md5sum_obtained = new char[80];

	sprintf(buffer,"md5sum %s",ptr);
	check_md5sum_stream = popen(buffer,"r");
	sleep(1);
	err = fscanf(check_md5sum_stream,"%s",md5sum_obtained);
	if(err == EOF || err == 0) {
		ui->label_check->setText("<font color=\"red\"><center>wrong file</center></font>");
	}
	if(strcmp(ARIA_MD5SUM,md5sum_obtained) != 0 ) {
		ui->label_check->setText("<font color=\"red\"><center>wrong file</center></font>");
	}
	else{
		ui->label_check->setText("<font color=\"green\"><center>good file</center></font>");
	}
	pclose(check_md5sum_stream);
}
/*
 * Method simply saves the current configuration into
 * ~/.config/aria/aria_manager.conf
 * */
void MainWindow::configuration_save() {
	settings.beginGroup("lineage_client");
	settings.setValue("updater_location",	path_to_ariaupdate);
	settings.setValue("window_width",	ui->textEdit->toPlainText());
	settings.setValue("window_height",	ui->textEdit_2->toPlainText());
	settings.endGroup();
	ui->label_check->setText("<font color=\"green\"><center>saved</center></font>");
	ui->label_check->setTextFormat(Qt::RichText);
}
/*
 * Couple of methods to serve launch buttons and
 * general method to rule them all ]:>
 * */
void MainWindow::run_client_1()	{run_client(1);}
void MainWindow::run_client_2()	{run_client(2);}
void MainWindow::run_client(int i){
	if(path_to_ariaupdate.isEmpty())
		return;
	// initial check if client isn't active already
	if(check_if_client_is_active(i) == true){
		switch(i){
		case 1:	ui->label_state_1->setText("<font color=\"green\"><center>active</center></font>");
			break;
		case 2:	ui->label_state_2->setText("<font color=\"green\"><center>active</center></font>");
			break;
		}
		return;
	}

	int err;
	char buffer[200];	
	QByteArray   bytes  = path_to_ariaupdate.toAscii();
	const char * ptr    = bytes.data();
	
	client_width	= (ui->textEdit->toPlainText()).toInt();
	client_height	= ui->textEdit_2->toPlainText().toInt();

	sprintf(buffer,"WINEDEBUG=-all wine explorer /desktop=LineageII_%d,%dx%d %s &",
			i, client_width, client_height, ptr);
	sleep(3);
	err = system(buffer);
	if(err < 0) {std::cout << "failed to call system process\n"; exit(1);}

	switch(i){
	case 1:	ui->label_state_1->setText("<font color=\"green\"><center>active</center></font>");
		break;
	case 2:	ui->label_state_2->setText("<font color=\"green\"><center>active</center></font>");
		break;
	}
}
/*
 * Again, couple of button handelers and main method to
 * close any client.
 * */
void MainWindow::close_client_1(){
	close_client(1);
}
void MainWindow::close_client_2(){
	close_client(2);
}
void MainWindow::close_client(int i){
	int	err;
	char	buffer[80];

	if(check_if_client_is_active(i) == false)
		return;

	sprintf(buffer,"kill %d",return_pid_of(i));
	err = system(buffer);
	if(err < 0) {std::cout << "failed to call system process\n"; exit(1);}
}
/*
 * Method for checking if there is a process with a proper name already
 * running. If yes - returns true, no - false.
 * */
bool MainWindow::check_if_client_is_active(int i){
	int err;
	char buffer[80];
	sprintf(buffer,"ps -ef | grep LineageII_%d | grep -v grep",i);
	err = system(buffer);
	if(err == 0) {	//client found
		switch(i){
		case 1:	ui->label_state_1->setText("<font color=\"orange\"><center>inactive</center></font>");
			break;
		case 2:	ui->label_state_2->setText("<font color=\"orange\"><center>inactive</center></font>");
			break;
		}
		return true;
	}
	else{		//client not found :(
		return false;
	}
}

/*
 * Like in title - returns pid
 * */
int MainWindow::return_pid_of(int i){
	int pid, err;
	char buffer[80];
	FILE* stream_for_ps;
	sprintf(buffer,"ps -ef | grep LineageII_%d | grep -v grep | awk  '{ print $2 }'",i);
	stream_for_ps = popen(buffer,"r");
	err = fscanf(stream_for_ps,"%d",&pid);
	pclose(stream_for_ps);
	if(err == EOF) {std::cout << "failed to get process pid\n"; exit(1);}
	return pid;
}
